package com.wangsh.forward.web.filter;

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wangsh.forward.system.pojo.ASysProperty;
import com.wangsh.forward.system.pojo.ASysPropertyEnum;
import com.wangsh.forward.system.service.ISystemService;
import com.wangsh.forward.system.service.impl.SystemServiceImpl;
import com.wangsh.webforward.common.pojo.ApiResponse;
import com.wangsh.webforward.common.pojo.ApiResponseEnum;
import com.wangsh.webforward.common.servlet.BaseServlet;
import com.wangsh.webforward.common.util.ConstatFinalUtil;

/**
 * 	编码过滤器
 * @author TeaBig
 */
public class CharacterFilter extends BaseServlet implements Filter
{
	private static final long serialVersionUID = 1L;
	
	/* 静态资源文件 */
	private String[] staticResource = {".css",".jpg",".png",".js"} ; 

	/* 配置编码 */
	private String encoding = ConstatFinalUtil.CHARSET ; 
	
	/* 用户的登录网址 */
	private String loginUrl = ConstatFinalUtil.CONFIG_JSON.getString("usersCenter.head.login.url") ; 
	/* 验证token的网址 */
	private String verifyTokenURL = ConstatFinalUtil.CONFIG_JSON.getString("usersCenter.outer.url") ; 
	/* 私钥 */
	private String usersCenterOuterPriKey = "wangshUsersCenter2019";
	/* 第二次访问次数 */
	private static int currCount = 1 ; 
	
	private ISystemService systemService;
	
	@Override
	public void initObject()
	{
		if(systemService == null || currCount < 3 )
		{
			systemService = new SystemServiceImpl() ; 
		}
		currCount ++ ; 
	}
	
	/**
	 * 初始化
	 */
	@Override
	public void init(FilterConfig filterConfig) throws ServletException
	{
		Filter.super.init(filterConfig);
		/* 获取配置文件中的编码 */
		String encodingPara = filterConfig.getInitParameter("encoding");
		ConstatFinalUtil.SYS_LOGGER.info("配置文件中编码:{}",encodingPara);
		if(encodingPara != null && !"".equalsIgnoreCase(encodingPara))
		{
			this.encoding = encodingPara ; 
		}
	}
	
	/**
	 * 核心过滤器必须要走的方法
	 */
	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException
	{
		/* 初始化对象 */
		this.initObject();
		
		HttpServletRequest request = (HttpServletRequest) req ;
		HttpServletResponse response = (HttpServletResponse) res ; 
		/* 设置公共信息 */
		this.commonInfo(request);
		//ConstatFinalUtil.SYS_LOGGER.info("编码过滤器执行;");
		/* 设置请求编码 */
		request.setCharacterEncoding(encoding);
		/* 设置响应编码 */
		response.setCharacterEncoding(this.encoding);
		
		/* url过滤 */
		String currUrl = request.getRequestURL() + ""; 
		
		/* 过滤静态资源文件 */
		if(this.staticFilter(request, response))
		{
			chain.doFilter(request, response);
			return ; 
		}
		
		/* 过滤系统的配置信息 */
		if(!this.sysPropertyConfig(request,response,chain))
		{
			return ; 
		}
		
		/* 前台网址的过滤 */
		String headIndex = "/head/" ; 
		if(currUrl.indexOf(headIndex) != -1)
		{
			/* 验证登陆 */
			this.headAuth(request,response,chain);
		}else
		{
			/* 放行 */
			chain.doFilter(request, response);
		}
	}

	/**
	 * 过滤静态资源文件
	 * @return
	 */
	private boolean staticFilter(HttpServletRequest request,HttpServletResponse response)
	{
		String currUrl = request.getRequestURL() + ""; 
		String queryStr = request.getQueryString() ; 
		/* 查询字符串 */
		if(queryStr != null && !"".equalsIgnoreCase(queryStr))
		{
			currUrl = currUrl + "?" + queryStr ; 
		}
		/* 判断资源文件 */
		for (int i = 0; i < staticResource.length; i++)
		{
			String resourceTemp = staticResource[i];
			if(currUrl.indexOf(resourceTemp) != -1)
			{
				/* 找到,直接放行 */
				return true ; 
			}
		}
		return false;
	}

	/**
	 * 检查系统的配置
	 * @return 
	 * true:检查通过,false:检查不通过;
	 */
	private boolean sysPropertyConfig(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException
	{
		String currUrl = request.getRequestURL() + ""; 
		String queryStr = request.getQueryString() ; 
		/* 查询字符串 */
		if(queryStr != null && !"".equalsIgnoreCase(queryStr))
		{
			currUrl = currUrl + "?" + queryStr ; 
		}
		String urlIndex = "main.htm?method=init"; 
		Map<String, Object> condMap = new HashMap<String, Object>();
		
		/* 存储tomcat所在的路径
		 * D:\Java\apache-tomcat\webapps\web-forward-web
		 *  */
		String pathTomcat = request.getRealPath("/");
		File pathTomcatFile = new File(pathTomcat);
		/* 要的是tomcat所在的路径 */
		pathTomcatFile = pathTomcatFile.getParentFile().getParentFile() ; 
		pathTomcat = pathTomcatFile.getAbsolutePath().replaceAll("\\\\", "/");
		ASysProperty sysProperty = new ASysProperty();
		sysProperty.setName("path.tomcat");
		sysProperty.setValue(pathTomcat);
		sysProperty.setContent("tomcat的绝对路径");
		sysProperty.setStatus(ASysPropertyEnum.STATUS_ENABLE.getStatus());
		sysProperty.setCreateTime(new Date());
		sysProperty.setUpdateTime(new Date());
		sysProperty.setPubTime(new Date());
		//ApiResponse<Object> apiResponseDb =  this.systemService.saveOnePropertyService(sysProperty);
		//ConstatFinalUtil.SYS_LOGGER.info("存储结果:{}",apiResponseDb.toJSON().toJSONString());
		ConstatFinalUtil.SYS_PRO_MAP.put(sysProperty.getName(), sysProperty.toJSON());
		
		/* 查询所有的系统配置 */
		condMap.clear();
		ApiResponse<ASysProperty> apiResponse = this.systemService.findCondListPropertyService(null, condMap);
		/* 系统配置的集合 */
		List<ASysProperty> dataListJava = apiResponse.getDataListJava() ; 
		/* 木有系统配置,url必须不是初始化的页面才可以
		 * dataListJava:肯定是刚刚添加的自己
		 *  */
		if(dataListJava.size() <= 1 && currUrl.indexOf(urlIndex) == -1)
		{
			/* 客户端跳转 */
			response.sendRedirect(request.getContextPath() + "/main.htm?method=init");
			return false; 
		}
		return true ; 
	}

	/**
	 * 前台用户登陆的过滤器
	 * @param request
	 * @param response
	 * @throws ServletException 
	 * @throws IOException 
	 */
	private void headAuth(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException
	{
		ConstatFinalUtil.SYS_LOGGER.info("--preHandle--");
		
		/* 请求头 */
		Map<String, String> headerMap = new HashMap<String, String>();
		/* 请求体 */
		Map<String, String> paramsMap = new HashMap<String, String>();
		/* 响应头 */
		Map<String, String> responseMap = new HashMap<String, String>();
		HttpSession session = request.getSession();
		
		JSONObject users = (JSONObject) session.getAttribute("users");
		/* 存储了usersJSON */
		if(users != null)
		{
			/* 放行 */
			chain.doFilter(request, response);
			return ; 
		}
		
		//ConstatFinalUtil.SYS_LOG.info("----1 preHandle(执行之后执行) ----");
		String[] tokens = request.getParameterValues("token");
		String token = "" ; 
		if(tokens != null && tokens.length > 0)
		{
			token = tokens[tokens.length - 1]; 
		}
		
		try
		{
			if(users == null && !"".equalsIgnoreCase(token))
			{
				/*
				 * 拼装上行的json
				 */
				/* 拼装上行信息 */
				JSONObject reqJSON = new JSONObject() ; 
				reqJSON.put("version", "1");
				reqJSON.put("method", "verifyUsersToken");
				reqJSON.put("pubKey", UUID.randomUUID().toString());
				reqJSON.put("time", System.currentTimeMillis() + "");
				
				/* 加密 */
				/* sha256,key加密 */
				HmacUtils hmacUtils = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, usersCenterOuterPriKey);
				/* 原字符串 */
				String souStr = reqJSON.getString("version") + 
						reqJSON.getString("pubKey") + reqJSON.getString("time") ; 
				/* 加密 */
				String encrypt = hmacUtils.hmacHex(souStr);
				reqJSON.put("encrypt", encrypt);
				
				JSONObject dataJSON = new JSONObject();
				dataJSON.put("token", token);
				reqJSON.put("data", dataJSON);
				
				paramsMap.put("json", reqJSON.toJSONString());
				/* 请求对方服务器 */
				String responseStr = httpUtil.methodPost(verifyTokenURL,headerMap,paramsMap,responseMap);
				
				JSONObject responseJSON = (JSONObject) JSON.parse(responseStr);
				if(responseJSON != null && responseJSON.getInteger("code") == ApiResponseEnum.STATUS_SUCCESS.getStatus())
				{
					//登陆成功
					dataJSON = (JSONObject) responseJSON.get("data");
					JSONObject usersJSON = dataJSON.getJSONObject("users");
					
					session.setAttribute("users", usersJSON);
					/* 放行 */
					chain.doFilter(request, response);
					return ; 
				}
			}
		} catch (Exception e)
		{
			ConstatFinalUtil.SYS_LOGGER.error("请求服务器报错了:{}",responseMap,e);
		}
		
		/* 加上returnUrl */
		String returnUrl = request.getRequestURL() + "";
		String queryStr = request.getQueryString() ;
		if(queryStr == null)
		{
			queryStr = "" ; 
		}
		returnUrl += "?" + queryStr ; 
		
		/* 对ReturnUrl进行encode加密 */
		String returnUrlEncode = URLEncoder.encode(returnUrl, "UTF-8");
		
		ConstatFinalUtil.SYS_LOGGER.info("---returnUrl:{}--returnUrlEncode:{}",returnUrl,returnUrlEncode);
		String loginUrl = this.loginUrl + "&returnUrl=" + returnUrlEncode ; 
		response.sendRedirect(loginUrl);
	}
}
